package com.reactim.message.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.annotation.Validated;

import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import com.reactim.message.config.validation.ValidBatchSizes;

/**
 * 性能测试配置类
 * 
 * <p>专门用于性能测试相关的配置属性，从application.yml中读取performance.test.*前缀的配置。
 * 该配置类提供了性能测试所需的各种参数设置，包括连接数限制、批次大小、线程数等。</p>
 * 
 * <h3>主要功能</h3>
 * <ul>
 *   <li><strong>连接数控制</strong> - 设置性能测试的最大连接数</li>
 *   <li><strong>批次配置</strong> - 定义测试使用的批次大小列表</li>
 *   <li><strong>线程配置</strong> - 定义测试使用的线程数列表</li>
 *   <li><strong>超时控制</strong> - 设置操作和测试的超时时间</li>
 *   <li><strong>清理策略</strong> - 配置测试后的清理行为</li>
 *   <li><strong>报告生成</strong> - 控制测试报告和指标导出</li>
 * </ul>
 * 
 * <h3>使用示例</h3>
 * <pre>{@code
 * @Autowired
 * private PerformanceTestConfig config;
 * 
 * public void runPerformanceTest() {
 *     // 获取最大连接数
 *     int maxConnections = config.getMaxConnections();
 *     
 *     // 遍历所有批次大小进行测试
 *     for (int batchSize : config.getBatchSizes()) {
 *         if (config.isValidBatchSize(batchSize)) {
 *             // 执行批次测试
 *             runBatchTest(batchSize);
 *         }
 *     }
 *     
 *     // 获取操作超时时间（毫秒）
 *     long timeoutMs = config.getOperationTimeoutMs();
 * }
 * }</pre>
 * 
 * <h3>配置验证</h3>
 * <p>该类包含完整的配置验证逻辑，通过{@link #isValid()}方法可以验证所有配置项的有效性。
 * 无效的配置会在应用启动时通过JSR-303验证注解抛出异常。</p>
 * 
 * <h3>配置示例</h3>
 * <pre>{@code
 * performance:
 *   test:
 *     max-connections: 100000
 *     batch-sizes: [1000, 5000, 10000, 20000]
 *     thread-counts: [5, 10, 20, 50, 100]
 *     operation-timeout-seconds: 30
 *     test-timeout-minutes: 30
 *     cleanup-after-test: true
 *     generate-detailed-report: true
 *     export-metrics: true
 * }</pre>
 * 
 * @author ReactIM Team
 * @version 1.0.0
 * @since 1.0.0
 * @see ReactimConfig.PerformanceProperties.TestProperties 统一配置中的性能测试配置
 */
@Configuration
@ConfigurationProperties(prefix = "performance.test")
@Validated
@Data
public class PerformanceTestConfig {
    
    /**
     * 最大连接数
     */
    @Min(value = 1, message = "最大连接数必须大于0")
    private int maxConnections = 100000;
    
    /**
     * 批次大小列表
     */
    @NotNull
    @ValidBatchSizes(minSize = 1, maxSize = 100000, minLength = 1)
    private int[] batchSizes = {1000, 5000, 10000, 20000};
    
    /**
     * 线程数列表
     */
    @NotNull
    private int[] threadCounts = {5, 10, 20, 50, 100};
    
    /**
     * 操作超时时间（秒）
     */
    @Min(value = 1, message = "操作超时时间必须大于0秒")
    private int operationTimeoutSeconds = 30;
    
    /**
     * 测试超时时间（分钟）
     */
    @Min(value = 1, message = "测试超时时间必须大于0分钟")
    private int testTimeoutMinutes = 30;
    
    /**
     * 是否在测试后清理
     */
    @NotNull
    private boolean cleanupAfterTest = true;
    
    /**
     * 清理超时时间（分钟）
     */
    @Min(value = 1, message = "清理超时时间必须大于0分钟")
    private int cleanupTimeoutMinutes = 5;
    
    /**
     * 是否生成详细报告
     */
    @NotNull
    private boolean generateDetailedReport = true;
    
    /**
     * 是否导出指标
     */
    @NotNull
    private boolean exportMetrics = true;
    
    /**
     * 获取操作超时时间（毫秒）
     * @return 超时时间（毫秒）
     */
    public long getOperationTimeoutMs() {
        return operationTimeoutSeconds * 1000L;
    }
    
    /**
     * 获取测试超时时间（毫秒）
     * @return 超时时间（毫秒）
     */
    public long getTestTimeoutMs() {
        return testTimeoutMinutes * 60 * 1000L;
    }
    
    /**
     * 获取清理超时时间（毫秒）
     * @return 超时时间（毫秒）
     */
    public long getCleanupTimeoutMs() {
        return cleanupTimeoutMinutes * 60 * 1000L;
    }
    
    /**
     * 检查是否为有效的批次大小
     * @param batchSize 批次大小
     * @return 是否有效
     */
    public boolean isValidBatchSize(int batchSize) {
        for (int size : batchSizes) {
            if (size == batchSize) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * 检查是否为有效的线程数
     * @param threadCount 线程数
     * @return 是否有效
     */
    public boolean isValidThreadCount(int threadCount) {
        for (int count : threadCounts) {
            if (count == threadCount) {
                return true;
            }
        }
        return false;
    }
    
    /**
     * 获取最大批次大小
     * @return 最大批次大小
     */
    public int getMaxBatchSize() {
        int max = 0;
        for (int size : batchSizes) {
            if (size > max) {
                max = size;
            }
        }
        return max;
    }
    
    /**
     * 获取最大线程数
     * @return 最大线程数
     */
    public int getMaxThreadCount() {
        int max = 0;
        for (int count : threadCounts) {
            if (count > max) {
                max = count;
            }
        }
        return max;
    }
    
    /**
     * 验证配置是否有效
     * @return 配置是否有效
     */
    public boolean isValid() {
        // 检查基本配置
        if (maxConnections <= 0) {
            return false;
        }
        if (operationTimeoutSeconds <= 0) {
            return false;
        }
        if (testTimeoutMinutes <= 0) {
            return false;
        }
        if (cleanupTimeoutMinutes <= 0) {
            return false;
        }
        
        // 检查数组配置
        if (batchSizes == null || batchSizes.length == 0) {
            return false;
        }
        if (threadCounts == null || threadCounts.length == 0) {
            return false;
        }
        
        // 检查数组中的值是否有效
        for (int size : batchSizes) {
            if (size <= 0) {
                return false;
            }
        }
        for (int count : threadCounts) {
            if (count <= 0) {
                return false;
            }
        }
        
        return true;
    }
}